package com.daoshu.mds.system.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.daoshu.component.exception.BusinessException;
import com.daoshu.mds.system.mapper.OrganizationMapper;
import com.daoshu.mds.system.service.IAccountRoleService;
import com.daoshu.mds.system.service.IAccountService;
import com.daoshu.mds.system.service.IOrganizationPersonService;
import com.daoshu.mds.system.service.IOrganizationService;
import com.daoshu.mds.system.service.IPersonService;
import com.daoshu.mds.system.service.IRoleService;
import com.daoshu.mds.system.utils.Constant;
import com.daoshu.system.bo.AccountBo;
import com.daoshu.system.bo.OrganizationBo;
import com.daoshu.system.bo.PersonBo;
import com.daoshu.system.entity.AccountRoleEntity;
import com.daoshu.system.entity.OrganizationEntity;
import com.daoshu.system.entity.OrganizationPersonEntity;
import com.daoshu.system.entity.PersonEntity;
import com.daoshu.system.entity.RoleEntity;
import com.daoshu.system.utils.RequestUtils;

import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zhaoyanjiang
 * @since 2018-09-17
 */
@Slf4j
@Service
public class OrganizationServiceImpl extends ServiceImpl<OrganizationMapper, OrganizationEntity> implements IOrganizationService {

	@Autowired
	private IOrganizationPersonService organizationPersonService;

	@SuppressWarnings("unused")
	@Autowired
	private IAccountService accountService;

	@Autowired
	private RequestUtils requestUtils;

	@Autowired
	private IRoleService roleService;

	@Autowired
	private IAccountRoleService accountRoleService;

	@Autowired
	private IPersonService personService;

	@Override
	public IPage<OrganizationEntity> getPage(OrganizationBo organizationBo) {
		OrganizationEntity condition = new OrganizationEntity();
		BeanUtils.copyProperties(organizationBo, condition);
		return this.page(new Page<>(organizationBo.getStart(), organizationBo.getSize()), new QueryWrapper<OrganizationEntity>(condition));
	}

//	@Cacheable(value = "orgTree", key = "#isBusiness + '_' + #rootId")
	@Override
	public List<OrganizationEntity> getOrgTree(Integer type, Integer contain, boolean isBusiness, String rootId) {
		List<OrganizationEntity> result = new ArrayList<OrganizationEntity>();

		List<OrganizationEntity> orgEntitys = null;
		/**
		 * 备用
		 * 	if(1 == type) {
		 * 			orgEntitys = this.list(new QueryWrapper<OrganizationEntity>().eq("type_", type).and(i->i.eq("region_id_",rootId).or().eq("region_pid_",rootId)).orderByDesc("internal_"));
		 *                } else {
		 * 			orgEntitys = this.list(new QueryWrapper<OrganizationEntity>().eq("region_id_",rootId).or().eq("region_pid_",rootId).orderByDesc("internal_"));
		 *        }
		 */
		if(1 == type) {
			orgEntitys = this.list(new QueryWrapper<OrganizationEntity>().eq("type_", type).orderByDesc("internal_"));
		} else {
			orgEntitys = this.list(new QueryWrapper<OrganizationEntity>().orderByDesc("internal_"));
		}

		Map<String, List<OrganizationEntity>> allChildren = new HashMap<String, List<OrganizationEntity>>();
		for (OrganizationEntity entity : orgEntitys) {
			if(0 == contain && StringUtils.isNotBlank(entity.getQu()) && entity.getQu().trim().equals(Constant.EXT_PRO_REGION)) {
				continue;
			}

			if (!allChildren.containsKey(isBusiness ? entity.getBusinessPid() : entity.getRegionPid())) {
				allChildren.put(isBusiness ? entity.getBusinessPid() : entity.getRegionPid(), new ArrayList<OrganizationEntity>());
			}
			allChildren.get(isBusiness ? entity.getBusinessPid() : entity.getRegionPid()).add(entity);
		}
		if(null!=allChildren.get(rootId)) {
			log.info("rootId is " + rootId);
			result.addAll(allChildren.get(rootId));
		}
		for (OrganizationEntity entity : result) {
			getResult(entity, allChildren);
		}
		return result;
	}

	/**
	 * 获取其他州市责任分局
	 * @param res
	 * @param allChildren
	 */
	@Override
	public List<OrganizationEntity>  getTreeZrfj(Integer type, Integer contain, boolean isBusiness, String rootId,String ssxq,String sspcs) {
		List<OrganizationEntity> result = new ArrayList<OrganizationEntity>();
		List<Map<String,Object>> map = new ArrayList<>();
		List<OrganizationEntity> orgEntitys = null;
		if(1 == type) {
			orgEntitys = this.list(new QueryWrapper<OrganizationEntity>().eq("type_", type).orderByDesc("internal_"));
		} else {
			orgEntitys = this.list(new QueryWrapper<OrganizationEntity>().orderByDesc("internal_"));
		}

		Map<String, List<OrganizationEntity>> allChildren = new HashMap<String, List<OrganizationEntity>>();
		for (OrganizationEntity entity : orgEntitys) {
			if(0 == contain && StringUtils.isNotBlank(entity.getQu()) && entity.getQu().trim().equals(Constant.EXT_PRO_REGION)) {
				continue;
			}

			if (!allChildren.containsKey(isBusiness ? entity.getBusinessPid() : entity.getRegionPid())) {
				allChildren.put(isBusiness ? entity.getBusinessPid() : entity.getRegionPid(), new ArrayList<OrganizationEntity>());
			}
			allChildren.get(isBusiness ? entity.getBusinessPid() : entity.getRegionPid()).add(entity);
		}
		if(null!=allChildren.get(rootId)) {
			log.info("rootId is " + rootId);
			result.addAll(allChildren.get(rootId));
		}
		for (OrganizationEntity entity : result) {
			getResult(entity, allChildren);
		}
		/**
		 * 组织其他州市责任分局
		 */
		List<OrganizationEntity> children = result.get(0).getChildren();
		List<OrganizationEntity> listZrzh = new ArrayList<>();
		for(OrganizationEntity organizationEntity:children){
			if(organizationEntity.getName().indexOf(ssxq) != -1){
				List<OrganizationEntity> children1 = organizationEntity.getChildren();
				for(OrganizationEntity organizationEntity1:children1){
					if(null != organizationEntity1.getShortName()){
						if(organizationEntity1.getShortName().indexOf("市局") != -1){
							//封装派出所
							List<OrganizationEntity> children2 = organizationEntity1.getChildren();
							List<OrganizationEntity> list = new ArrayList<>();
							if(null != children2 && children2.size() > 0){
								for(OrganizationEntity organizationEntity2:children2){
									if(null != organizationEntity2.getShortName()){
										if(organizationEntity2.getShortName().indexOf("派出所") != -1){
											list.add(organizationEntity2);
										}
									}
								}
							}
							organizationEntity1.setChildren(list);
							listZrzh.add(organizationEntity1);
						}else if(organizationEntity1.getShortName().indexOf("县局") != -1){
							//封装派出所
							List<OrganizationEntity> children2 = organizationEntity1.getChildren();
							List<OrganizationEntity> list = new ArrayList<>();
							if(null != children2 && children2.size() > 0){
								for(OrganizationEntity organizationEntity2:children2){
									if(null != organizationEntity2.getShortName()){
										if(organizationEntity2.getShortName().indexOf("派出所") != -1){
											list.add(organizationEntity2);
										}
									}
								}
							}
							organizationEntity1.setChildren(list);
							listZrzh.add(organizationEntity1);
						}else if(organizationEntity1.getShortName().indexOf("分局") != -1){
							//封装派出所
							List<OrganizationEntity> children2 = organizationEntity1.getChildren();
							List<OrganizationEntity> list = new ArrayList<>();
							if(null != children2 && children2.size() > 0){
								for(OrganizationEntity organizationEntity2:children2){
									if(null != organizationEntity2.getShortName()){
										if(organizationEntity2.getShortName().indexOf("派出所") != -1){
											list.add(organizationEntity2);
										}
									}

								}
							}
							organizationEntity1.setChildren(list);
							listZrzh.add(organizationEntity1);
						}
					}

				}
			}
		}
		return listZrzh;
	}

	private void getResult(OrganizationEntity res, Map<String, List<OrganizationEntity>> allChildren) {
		List<OrganizationEntity> children = allChildren.get(res.getId());
		if (!Collections.isEmpty(children)) {
			res.setChildren(children);
			for (OrganizationEntity entity : children) {
				getResult(entity, allChildren);
			}
		}
	}

	/**
	 * 通过传递的key和value 将list转换为map
	 * @Title: listToMap
	 * @Description: TODO
	 * @param pIdToCount
	 * @param key
	 * @param value
	 * @return
	 * @return: Map<String,String>
	 */
	private Map<String, String> listToMap(List<Map<String, Object>> pIdToCount, String key, String value){
		pIdToCount.sort((Map<String, Object> map1, Map<String, Object> map2) -> Optional.ofNullable(map1.get("1")).orElse("").toString().compareTo(Optional.ofNullable(map2.get("1")).orElse("").toString()));
		Map<String, String> result = new HashMap<String, String>();
		if(!Collections.isEmpty(pIdToCount)) {
			for(Map<String, Object> map : pIdToCount) {
				result.put(Optional.ofNullable(map.get(key)).orElse(""
				).toString(), Optional.ofNullable(map.get(value)).orElse("").toString());
			}
		}
		return result;
	}

	/**
	 * 获取组织下的人员数量
	 * @Title: getPersonCount
	 * @Description: TODO
	 * @param orgId
	 * @param orgIdToOrgIds
	 * @param orgIdToPersonCount
	 * @return
	 * @return: int
	 */
	private int getPersonCount(String orgId, Map<String, String> orgIdToOrgIds, Map<String, String> orgIdToPersonCount) {
		int count = 0;
		if (orgIdToPersonCount.containsKey(orgId)) {
			count = Integer.valueOf(orgIdToPersonCount.get(orgId));
		}
		if (orgIdToOrgIds.containsKey(orgId)) {
			String[] childIds = orgIdToOrgIds.get(orgId).split(",");
			for (String childId : childIds) {
				count += getPersonCount(childId, orgIdToOrgIds, orgIdToPersonCount);
			}
		}
		return count;
	}

	/**
	 * @Title: getpIdToIds
	 * @Description: TODO
	 * @param isBusiness
	 * @param isInternal
	 * @return
	 * @return: List<Map<String,Object>>
	 */
	private List<Map<String, Object>> getpIdToIds(boolean isBusiness, Boolean isInternal) {
		QueryWrapper<OrganizationEntity> wrapper = new QueryWrapper<OrganizationEntity>();
		wrapper.select(isBusiness ? "business_pid_ pid" : "region_pid_ pid", "array_to_string(array_agg(id_), ',') ids");
		if (null != isInternal) {
			wrapper.eq("internal_", isInternal ? 1 : 0);
		}
		wrapper.groupBy(isBusiness ? "business_pid_" : "region_pid_");
		wrapper.isNotNull(isBusiness ? "business_pid_" : "region_pid_");
		return this.listMaps(wrapper);
	}

	@Override
	public List<OrganizationEntity> getDetailByPId(boolean isBusiness, String pId, Boolean isInternal,boolean systemUserFlag) {
		QueryWrapper<OrganizationEntity> queryWrapper = new QueryWrapper<OrganizationEntity>();
		if (null != isInternal) {
			queryWrapper.eq("internal_", isInternal ? 1 : 0);
		}
		queryWrapper.eq(isBusiness ? "business_pid_" : "region_pid_", pId).orderByAsc("sort_");
		List<OrganizationEntity> organizationEntitys = this.list(queryWrapper);
		Map<String, String> external = listToMap(getpIdToIds(isBusiness, false), "pid", "ids");
		Map<String, String> internal = listToMap(getpIdToIds(isBusiness, true), "pid", "ids");
		Map<String, String> allChild = new HashMap<String, String>();
		allChild.putAll(external);
		allChild.putAll(internal);
		// 获取所有的人员信息
		QueryWrapper<OrganizationPersonEntity> perQueryWrapper = new QueryWrapper<OrganizationPersonEntity>().select("org_id_ orgid", "count(id_) count").groupBy("org_id_");

		List<Map<String, Object>> personCounts = organizationPersonService.listMaps(perQueryWrapper);
		Map<String, String> orgIdToPersonCountMap = listToMap(personCounts, "orgid", "count");
		if (!Collections.isEmpty(organizationEntitys)) {
			organizationEntitys.parallelStream().forEach(organizationEntity -> {
				if (internal.containsKey(organizationEntity.getId())) {
					organizationEntity.setExistInternal(true);
				}
				if (external.containsKey(organizationEntity.getId())) {
					organizationEntity.setExistExternal(true);
				}
				organizationEntity.setPersonCount(getPersonCount(organizationEntity.getId(), allChild, orgIdToPersonCountMap));
			});
		}
		return organizationEntitys;
	}
	
	@Override
	public List<OrganizationEntity> getOrgByPId(String orgType, String pId, String keyword) {
		QueryWrapper<OrganizationEntity> queryWrapper = new QueryWrapper<>();
		if (null != keyword) {
			queryWrapper.like("short_name_", keyword);
		}
		//派出所类型条件
		queryWrapper.eq("org_type_", Integer.parseInt(orgType));
		queryWrapper.eq("region_pid_", pId).orderByAsc("sort_");
		List<OrganizationEntity> organizationEntitys = this.list(queryWrapper);
		
		return organizationEntitys;
	}
	
	@Override
	public  OrganizationEntity  getOrgById(boolean isBusiness, String id, Boolean isInternal,boolean systemUserFlag) {
		QueryWrapper<OrganizationEntity> queryWrapper = new QueryWrapper<OrganizationEntity>();
		if (null != isInternal) {
			queryWrapper.eq("internal_", isInternal ? 1 : 0);
		}
		//派出所类型条件
		//queryWrapper.eq("org_type_", 3);
		queryWrapper.eq("region_id_", id).orderByAsc("sort_");
		OrganizationEntity organizationEntity  = this.getOne(queryWrapper); 
		return organizationEntity;
	}

    @Override
    public List<OrganizationEntity> getListByRegionId(String regionId) {

		return this.baseMapper.getListByRegionId(regionId);
    }

    @Override
	public List<OrganizationEntity> getOrgByOrgtype(String type) {
		QueryWrapper<OrganizationEntity> queryWrapper = new QueryWrapper<OrganizationEntity>();
		//派出所类型条件
		queryWrapper.eq("org_type_", Integer.parseInt(type));
		queryWrapper.eq("type_", 1);  //对系统有效的组织类型
		List<OrganizationEntity> organizationEntitys = this.list(queryWrapper);
		
		return organizationEntitys;
	}

	@Override
	public List<String> getAllChild(String sIds, boolean containsAll, boolean isBusiness) {
		List<OrganizationEntity> entitys = this.list(new QueryWrapper<OrganizationEntity>().in("id_", Arrays.asList(sIds.split(","))));
		List<String> ids = new ArrayList<String>();
		entitys.parallelStream().forEach(item -> {ids.add(item.getId());});
		List<String> result = new ArrayList<String>();
		if (containsAll) {
			Map<String, String> pIdToIdsMap = listToMap(this.getpIdToIds(isBusiness, null), "pid", "ids");
			getAllChildTemp(pIdToIdsMap, ids, result);
		}
		return result;
	}

	private void getAllChildTemp(Map<String, String> pIdToIdsMap, List<String> ids, List<String> result){
		for (String str : ids) {
			result.add(str);
			if (pIdToIdsMap.containsKey(str)) {
				List<String> list = Arrays.asList(pIdToIdsMap.get(str).split(","));
				getAllChildTemp(pIdToIdsMap, list, result);
			}
		}
	}

	@Override
	public List<OrganizationEntity> getOrgByCurrentUserId() throws BusinessException{
		List<OrganizationEntity> result = new ArrayList<>();

		AccountBo accountBo = null;

		try {
			accountBo = requestUtils.getCurrentUser();
		}catch (BusinessException e){
			throw new BusinessException(401, "登录超时,请重新登录");
		}

		AccountRoleEntity accountRoleEntity = new AccountRoleEntity();
		accountRoleEntity.setAccountId(accountBo.getId());
		QueryWrapper<AccountRoleEntity> queryWrapper = new QueryWrapper<>(accountRoleEntity);
		List<AccountRoleEntity> accountRoleEntityList = accountRoleService.list(queryWrapper);
		if (null != accountRoleEntityList && accountRoleEntityList.size() > 0) {
			accountRoleEntity = accountRoleEntityList.get(0);

			RoleEntity roleEntity =  roleService.getById(accountRoleEntity.getRoleId());
			if (null != roleEntity) {
				// 1 市局情指中心用户
				// 2 分局情指中心用户
                // 3 派出所用户
                // 4 民警
				// 5 指挥中心
				if ("1".equals(roleEntity.getId()) || "5".equals(roleEntity.getId())) {
					log.error("current role id is " + roleEntity.getId());
					String curOrgId = accountBo.getOrganizationBo().getId();
					log.error("current org id is " + curOrgId);
					List<OrganizationEntity> entities = this.list(new QueryWrapper<OrganizationEntity>().select("qu_").eq("available_", 1).groupBy("qu_, region_id_"));
					entities.forEach(entity -> {
						if (null != entity) {
							if(StringUtils.isNotBlank(entity.getQu())) {
								OrganizationEntity organizationEntity = new OrganizationEntity();
								organizationEntity.setShortName(entity.getQu() + "分局");
								organizationEntity.setQu(entity.getQu());
								log.error("region id is " + entity.getRegionId());
								organizationEntity.setRegionId(entity.getRegionId());
								result.add(organizationEntity);
							}
						}
					});
				} else if ("2".equals(roleEntity.getId())) {
					OrganizationEntity organizationEntity = this.getById(accountBo.getOrganizationBo().getId());
					List<OrganizationEntity> organizations = this.list(new QueryWrapper<OrganizationEntity>().eq("qu_", organizationEntity.getQu()));
					organizations.forEach(organization -> {
						if (null != organization) {
							if (StringUtils.isNotBlank(organization.getName())) {
								if (organization.getName().indexOf("派出所") > -1) {
									result.add(organization);
								}
							}
						}
					});
				} else if ("3".equals(roleEntity.getId())) {
                    OrganizationEntity organizationEntity = this.getById(accountBo.getOrganizationBo().getId());
                    List<PersonEntity> personEntityList = personService.getPersonsByOrgId(organizationEntity.getId());
                    personEntityList.forEach(personEntity -> {
                        OrganizationEntity organization = new OrganizationEntity();
                        organization.setName(personEntity.getName());
                        organization.setConcatPhone(personEntity.getPhone());
						organization.setNumber(personEntity.getNumber());
                        result.add(organization);
                    });
                } else if ("4".equals(roleEntity.getId())) {
                    OrganizationEntity organization = new OrganizationEntity();
                    PersonBo personBo = accountBo.getPersonBo();
                    organization.setName(personBo.getName());
                    organization.setConcatPhone(personBo.getPhone());
					organization.setNumber(personBo.getNumber());
                    result.add(organization);
                }
			}
		}
		return result;
	}

	/**
	 * 通过当前用户获取对应组织机构
	 *
	 * @param accountBo
	 * @return
	 */
	@Override
	public List<OrganizationEntity> getOrgByCurrentUserId(final AccountBo accountBo, final int type) {
		List<OrganizationEntity> result = new ArrayList<>();

		AccountRoleEntity accountRoleEntity = new AccountRoleEntity();
		accountRoleEntity.setAccountId(accountBo.getId());
		QueryWrapper<AccountRoleEntity> queryWrapper = new QueryWrapper<>(accountRoleEntity);
		List<AccountRoleEntity> accountRoleEntityList = accountRoleService.list(queryWrapper);
		if (null != accountRoleEntityList && accountRoleEntityList.size() > 0) {
			accountRoleEntity = accountRoleEntityList.get(0);

			RoleEntity roleEntity =  roleService.getById(accountRoleEntity.getRoleId());
			if (null != roleEntity) {
				// 1 市局情指中心用户
				// 2 分局情指中心用户
				// 3 派出所用户
				// 4 民警
				// 5 指挥中心
				if ("1".equals(roleEntity.getId()) || "5".equals(roleEntity.getId())) {
					log.error("current role id is " + roleEntity.getId());
					String curOrgId = "131000000000";
					log.error("current org id is " + curOrgId);
					List<OrganizationEntity> entities = this.list(new QueryWrapper<OrganizationEntity>().select("qu_, region_id_").eq("available_", 1).eq("region_pid_", curOrgId).eq(false, "qu_", "NULL").groupBy("qu_, region_id_"));
					OrganizationEntity externalOrg = new OrganizationEntity();
					entities.forEach(entity -> {
						if (null != entity) {
							if(StringUtils.isNotBlank(entity.getQu())) {
								if(StringUtils.isNotBlank(entity.getQu()) && entity.getQu().trim().equals(Constant.EXT_PRO_REGION)) {
									BeanUtils.copyProperties(entity, externalOrg);
									externalOrg.setShortName(entity.getQu());
								} else {
									OrganizationEntity organizationEntity = new OrganizationEntity();
									organizationEntity.setShortName(entity.getQu() + "分局");
									organizationEntity.setQu(entity.getQu());
									log.error("region id is " + entity.getRegionId());
									organizationEntity.setRegionId(entity.getRegionId());
									result.add(organizationEntity);
								}
							}
						}
					});

					if(1 == type) {
						result.add(externalOrg);
					}
				} else if ("2".equals(roleEntity.getId())) {
					OrganizationEntity organizationEntity = this.getById(accountBo.getOrganizationBo().getId());
					List<OrganizationEntity> organizations = this.list(new QueryWrapper<OrganizationEntity>().eq("qu_", organizationEntity.getQu()));
					organizations.forEach(organization -> {
						if (null != organization) {
							if (StringUtils.isNotBlank(organization.getName())) {
								if (organization.getName().indexOf("派出所") > -1) {
									result.add(organization);
								}
							}
						}
					});
				} else if ("3".equals(roleEntity.getId())) {
					OrganizationEntity organizationEntity = this.getById(accountBo.getOrganizationBo().getId());
					List<PersonEntity> personEntityList = personService.getPersonsByOrgId(organizationEntity.getId());
					personEntityList.forEach(personEntity -> {
						OrganizationEntity organization = new OrganizationEntity();
						organization.setName(personEntity.getName());
						organization.setConcatPhone(personEntity.getPhone());
						organization.setNumber(personEntity.getNumber());
						result.add(organization);
					});
				} else if ("4".equals(roleEntity.getId())) {
					OrganizationEntity organization = new OrganizationEntity();
					PersonBo personBo = accountBo.getPersonBo();
					organization.setName(personBo.getName());
					organization.setConcatPhone(personBo.getPhone());
					organization.setNumber(personBo.getNumber());
					result.add(organization);
				}
			}
		}
		return result;
	}

	/**
     * 根据当父id查询组织机构
     *
     * @param parentId 父id
     * @param type
     * @return
     */
	@SuppressWarnings("unchecked")
	@Override
    public List<OrganizationEntity> getOrgByParentId(String parentId, Integer type) {
        OrganizationEntity organizationEntity = new OrganizationEntity();
        organizationEntity.setRegionPid(parentId);
        organizationEntity.setAvailable(1);
        
	    QueryWrapper<?> queryWrapper = null;
	    if(1 == type) {
	    	queryWrapper = new QueryWrapper<Object>(organizationEntity).eq("type_", type);
	    } else {
	    	queryWrapper = new QueryWrapper<Object>(organizationEntity);
	    }
	    
	    List<OrganizationEntity> organizationEntityList = this.list((Wrapper<OrganizationEntity>) queryWrapper);
        return organizationEntityList;
    }
}
